package com.thread.async;

import java.util.concurrent.*;

/**
 * @author wangyingjie
 * @date
 * @remark 线程之间相互等待
 */
public class CyclicBarrierDemo {

    /**
     * 线程计数器
     */
    static CyclicBarrier cyclicBarrier = new CyclicBarrier(10);

    public static void main(String[] args) throws InterruptedException {
        //异步开启10个线程，等待10个线程全部完成，再继续执行主线程
        ExecutorService threadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            threadPool.submit(() -> {
                try {
                    test(cyclicBarrier);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    //这个cycleBarrier已经破坏，无法等待所有线程完成，需重新处理。例如其中一个线程异常中断了，其他9个线程会抛出这个异常，因为结构已经破坏，无法等到计数器到10，避免了线程永久等待
                    e.printStackTrace();
                } catch (TimeoutException e) {
                    e.printStackTrace();
                }finally {

                }

            });
        }
        //主线程自己执行，不等待
        System.out.println("主线程自己执行，不等待。。计数器此时是"+cyclicBarrier.getNumberWaiting());
        threadPool.shutdown();
    }

    /**
     * 执行任务的方法
     * cyclicBarrier内的线程相互等待
     * @param count
     */
    private static void test(CyclicBarrier count) throws InterruptedException, BrokenBarrierException, TimeoutException {
        Thread.sleep(1000);
        System.out.println("线程阻塞。。。");
        //该条线程阻塞，并且计数器+1.阻塞2秒后，直接继续执行
        cyclicBarrier.await(2,TimeUnit.SECONDS);
        System.out.println("线程阻塞恢复执行，等待的线程计数是："+cyclicBarrier.getNumberWaiting());
    }
}
